/*
 * Copyright 2014 http://Bither.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.photoeditor.demo.util;


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.text.TextUtils;
import android.util.Base64;

import com.common.base.ComponentContext;
import com.photoeditor.R;
import com.photoeditor.demo.model.image.util.ImageHelper;
import com.photoeditor.demo.util.transformation.BlurTransformation;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class ImageManageUtil {
    public static final int IMAGE_WIDTH = 612;
    public static final int MIDDLE_IMAGE_WIDTH = 305;
    public static final int SMALL_IMAGE_WIDTH = 160;
    public static final int MICRO_IMAGE_WIDTH = 80;
    public static final int IMAGE_SAVE_WIDTH = IMAGE_WIDTH * 2;
    public static final int IMAGE_ME_SAVE_QUALITY = 80;
    public static final int IMAGE_PICTURES_SAVE_QUALITY = 95;
    public static int PIIMAGE_MIDLLE_SIZE = getScreenWidth() - dip2pix(10);

    public static final int dip2pix(float dip) {
        final float scale = ComponentContext.getContext().getResources()
                .getDisplayMetrics().density;
        return (int) (dip * scale + 0.5f);
    }

    public static final int getSmallImageCacheWidth() {
        //12 * 2 - 8 * 2
        return Math.min((getScreenWidth() - dip2pix(10) * 4) / 3,
                SMALL_IMAGE_WIDTH);
    }

    public static final int getMcroImageCacheWidth() {
        return Math.min(getScreenWidth() / 9,
                MICRO_IMAGE_WIDTH);
    }


    public static int getScreenWidth() {
        return ComponentContext.getContext().getResources().getDisplayMetrics().widthPixels;
    }

    public static int getScreenHeight() {
        return ComponentContext.getContext().getResources().getDisplayMetrics().heightPixels;
    }

    /**
     * 将图片转换成Base64编码的字符串
     *
     * @param path
     * @return base64编码的字符串
     */
    public static String imageToBase64(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        InputStream is = null;
        byte[] data = null;
        String result = null;
        try {
            is = new FileInputStream(path);
            //创建一个字符流大小的数组。
            data = new byte[is.available()];
            //写入数组
            is.read(data);
            //用默认的编码格式进行编码
            result = Base64.encodeToString(data, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    /**
     * base64编码字符集转化成图片文件。
     *
     * @param base64Str
     * @param path      文件存储路径
     * @return 是否成功
     */
    public static boolean base64ToFile(String base64Str, String path) {
        byte[] data = Base64.decode(base64Str, Base64.DEFAULT);
        for (int i = 0; i < data.length; i++) {
            if (data[i] < 0) {
                //调整异常数据
                data[i] += 256;
            }
        }
        OutputStream os = null;
        try {
            os = new FileOutputStream(path);
            os.write(data);
            os.flush();
            os.close();
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    public static Bitmap base64ToBitmap(String base64Data) {
        byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }

    // 按大小缩放
    public static Bitmap getImageBitmap(String srcPath) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
        float hh = 800f;// 这里设置高度为800f
        float ww = 480f;// 这里设置宽度为480f
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        // 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
    }

    // 图片质量压缩
    private static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    private static final String TAG = "ImageManageUtil";
    public interface IFuzzyBackgroundListener{
        void onSuccess(Bitmap bitmap);
        void onError(Throwable throwable);
    }

    /**
     * 模糊背景生成方法，已经做子线程处理图片，主线程回调结果。直接使用，关注最后的结果就ok
     * 不需要判空
     * @param bitmapRes
     * @param iFuzzyBackgroundListener
     * @return 可以取消的句柄
     */
    public static Disposable genFuzzyBackground(final Bitmap bitmapRes ,final IFuzzyBackgroundListener iFuzzyBackgroundListener) {
        return Observable.create(new ObservableOnSubscribe<Bitmap>() {
            @Override
            public void subscribe(ObservableEmitter<Bitmap> emitter) throws Exception {
                CameraDrawable mSrcBitmap = new CameraDrawable(ComponentContext.getContext().getResources(),bitmapRes );
                Bitmap backgroundBitmap = createBackgroundBitmap(mSrcBitmap.getBitmap());
                emitter.onNext(backgroundBitmap);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bitmap) throws Exception {
                        if (bitmap != null) {
                            FLogUtils.i(TAG, "FuzzyBackground onSuccess");
                            if (iFuzzyBackgroundListener != null) {
                                iFuzzyBackgroundListener.onSuccess(bitmap);
                            }
                        } else {
                            if (iFuzzyBackgroundListener != null) {
                                iFuzzyBackgroundListener.onError(new Throwable("bitmap is null"));
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        FLogUtils.e(TAG, throwable);
                        if (iFuzzyBackgroundListener != null) {
                            iFuzzyBackgroundListener.onError(throwable);
                        }
                    }
                });
    }


    //生成背景和贴纸背景
    private static Bitmap createBackgroundBitmap(Bitmap srcBitmap) {
        int scaleRatio = 5;
        if (srcBitmap == null || srcBitmap.isRecycled()) {
            return null;
        }
        Bitmap blurBitmap = srcBitmap.createScaledBitmap(srcBitmap,
                srcBitmap.getWidth() / scaleRatio,
                srcBitmap.getHeight() / scaleRatio,
                false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            blurBitmap = BlurTransformation.blur(ComponentContext.getContext(), blurBitmap, 25);
        } else {
            blurBitmap = FastBlur.doBlur(blurBitmap, 25, true);
        }

        //stickerBg
        Bitmap mStickerViewBg = Bitmap.createBitmap(ImageHelper.SCREEN_WIDTH, (int) ComponentContext.getContext().getResources().getDimension(R.dimen.image_edit_emoji_panel_height), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mStickerViewBg);
        Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        int bitmapHeight = (int) (mStickerViewBg.getHeight() * blurBitmap.getWidth() * 1.0f / ImageHelper.SCREEN_WIDTH);
        canvas.drawBitmap(blurBitmap, new Rect(0, blurBitmap.getHeight() - bitmapHeight, blurBitmap.getWidth(), blurBitmap.getHeight()), new Rect(0, 0, mStickerViewBg.getWidth(), mStickerViewBg.getHeight()), bitmapPaint);
        canvas.drawColor(ComponentContext.getContext().getResources().getColor(R.color.sticker_bg_cover));

        //background
        Bitmap mBackgroundBitmap = Bitmap.createBitmap(blurBitmap.getWidth(), blurBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas1 = new Canvas(mBackgroundBitmap);
        bitmapPaint.setAlpha(30);
        canvas1.drawBitmap(blurBitmap, 0, 0, bitmapPaint);
        blurBitmap.recycle();
        return mBackgroundBitmap;
    }

}
